#include "config_parser.h"
#include "vendor_global.h"
#include <map>
#include <stdlib.h>
#include <utils/macro.h>

#define CHECK_MAP_KEY(kv, key)                                   \
    do {                                                         \
        if (kv.find(#key) == kv.end()) {                         \
            HTELINK_LOG_ERR("dataCenter config not found" #key); \
            return;                                              \
        }                                                        \
    } while (0)

namespace settings {
ConfigParser::ConfigParser() : xmlConfig_(new XmlConfig())
{
    if (!xmlConfig_->Load(VENDOR_CONFIG_PATH + "/basic_config.xml")) {
        HTELINK_LOG_ERR("load xml failed");
    }
}

ConfigParser::~ConfigParser()
{
    delete xmlConfig_;
}

std::vector<ConfigParser::DataCenter> ConfigParser::GetDataCenter() const
{
    std::vector<DataCenter> dataCenters;
    xmlConfig_->GetElemValue("dataCenter", [&dataCenters](std::map<std::string, std::string> &kv) -> void {
        DataCenter center;
        CHECK_MAP_KEY(kv, name);
        CHECK_MAP_KEY(kv, id);
        CHECK_MAP_KEY(kv, host);
        CHECK_MAP_KEY(kv, port);
        CHECK_MAP_KEY(kv, key);
        CHECK_MAP_KEY(kv, tls);
        center.name = kv["name"];
        center.ID = kv["id"];
        center.host = kv["host"];
        center.port = atoi(kv["port"].c_str());
        center.protoType = 1;
        center.key = kv["key"];
        center.isTls = atoi(kv["tls"].c_str()) != 0;
        center.yunID = 0;
        dataCenters.push_back(center);
    });
    // 兼容老版本格式
    if (dataCenters.empty()) {
        DataCenter center;
        center.ID = xmlConfig_->GetElemValueString("", "id");
        center.host = xmlConfig_->GetElemValueString("", "host");
        center.port = xmlConfig_->GetElemValueInt("", "port");
        center.key = xmlConfig_->GetElemValueString("", "key");
        center.isTls = xmlConfig_->GetElemValueBool("", "tls");
        center.protoType = 1;
        center.yunID = 0;
        dataCenters.push_back(center);
    }
    return dataCenters;
}

std::vector<ConfigParser::LoginUser> ConfigParser::GetLoginUsers() const
{
    std::vector<LoginUser> loginUsers;
    xmlConfig_->GetElemValue("logUser", [&loginUsers](std::map<std::string, std::string> &kv) -> void {
        LoginUser user;
        CHECK_MAP_KEY(kv, username);
        CHECK_MAP_KEY(kv, host);
        user.user = kv["username"];
        user.passwd = kv["password"];
        loginUsers.push_back(user);
    });
    // 兼容老版本格式
    if (loginUsers.empty()) {
        LoginUser user;
        user.user = xmlConfig_->GetElemValueString("", "username");
        user.passwd = xmlConfig_->GetElemValueString("", "password");
        loginUsers.push_back(user);
    }
    return loginUsers;
}

int16_t ConfigParser::GetWWWPort() const
{
    return xmlConfig_->GetElemValueInt("", "wwwPort");
}

int32_t ConfigParser::GetRetryTimes()
{
    return xmlConfig_->GetElemValueInt("", "retry");
}

std::unordered_map<std::string, ConfigParser::Channel> ConfigParser::GetChannels() const
{
    std::unordered_map<std::string, Channel> channels;

    std::vector<DataCenter> dataCenters;
    xmlConfig_->GetElemValue("Channel", [&channels](std::map<std::string, std::string> &kv) -> void {
        for (std::pair<std::string, std::string> chn : kv) {
            Channel chnn;
            chnn.devPath = chn.second;
            if (utils::StartWith(chn.first, "COM")) {
                chnn.type = CHN_COM;
            } else if (utils::StartWith(chn.first, "TCP")) {
                chnn.type = CHN_TCP;
            } else if (utils::StartWith(chn.first, "UDP")) {
                chnn.type = CHN_UDP;
            } else if (utils::StartWith(chn.first, "LORA")) {
                chnn.type = CHN_LORA;
            } else {
                chnn.type = CHN_COM;
            }
            channels[chn.first] = chnn;
        }
    });
    // 兼容老版本格式
    if (channels.empty()) {
        std::string chanStr = xmlConfig_->GetElemValueString("", "portNames");
        std::vector<std::string> chanList = utils::Split(chanStr, ",");
        int32_t index = 1;
        for (const std::string &chn : chanList) {
            if (chn.empty()) {
                continue;
            }
            Channel chnn;
            chnn.devPath = chn;
            chnn.type = CHN_COM;
            channels["COM" + index++] = chnn;
        }
    }
    return channels;
}
int32_t ConfigParser::GetLogDuration() const
{
	return xmlConfig_->GetElemValueInt("", "logStoreDuration");
}

ConfigParser::Channel ConfigParser::FindChannel(const std::string &name)
{
	std::unordered_map<std::string, ConfigParser::Channel> mapChannels =
		GetChannels();
	if (mapChannels.find(name) == mapChannels.end()) {
		ConfigParser::Channel chn;
		chn.type = CHN_MAX;
		return chn;
	}
	return mapChannels[name];
}
} // namespace settings
